package com.lucenten.collect.gnss.handler.files;

import cn.quevo.common.lang.DateFormatUtils;
import cn.quevo.common.lang.NumberUtils;
import cn.quevo.common.lang.StringUtils;
import com.lucenten.collect.gnss.entity.GnssFile;
import com.lucenten.collect.gnss.enums.PathFileType;
import com.lucenten.collect.gnss.handler.tools.TecDateFormat;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

/**
 * 解析路径数据的工具类
 *
 * @author July july_sky@foxmail.com
 * @version 1.0
 * @date 2019/5/3 11:33
 * @Copyright 东方浩星（北京）传媒科技有限公司版权所有.All Rights Reserved.
 */
@Slf4j
public class PathFilesBak {

    public Double[][] readPathData(Path file, boolean isVerTow, PathFileType pathFileType, GnssFile gnssFile) {
        if (Files.notExists(file)) {
            return null;
        }
        List<String> lines =null;
        try {
            lines = Files.readAllLines(file);
        } catch (IOException e) {
            log.error("路径文件读取失败["+file.getFileName().normalize().toFile()+"]",e);
            return null;
        }
        int index = getDataIndex(lines);
        if (index >= lines.size()) {
            return null;
        }
        //卫星轨道参数数组：32颗卫星，31个参数
        Double[][] pathData = new Double[32][31];
        if (pathFileType == PathFileType.G) {
            pathData = new Double[24][17];
        }
        // 卫星编号
        Integer startNum = 0;
        // 导航时间
        String dateTime = "";
        String line = "";
        int startLength = isVerTow ? 3 : 4;
        double[] singlePath = null;
        for (; index < lines.size(); index ++) {
            line = lines.get(index);
            //79 = 19 * 4 + 3
            //80 = 19 * 4 + 4
            if (StringUtils.isBlank(line) || line.length() < 19 * 3 + startLength) {
                continue;
            }
            // 卫星号
            startNum = NumberUtils.toInt(line.substring(startLength - 3, startLength - 1).trim());
            if (StringUtils.isBlank(startNum)) {
                continue;
            }
            // 导航时间
            dateTime = line.substring(startLength - 1, 19 + startLength);
            if (StringUtils.isBlank(dateTime)) {
                return null;
            }
            startNum = startNum - 1;
            singlePath = readSinglePath(lines, index, startNum, startLength, pathFileType,dateTime, gnssFile.getYear().toString());
            this.checkSinglePath(pathData, singlePath, startNum, TecDateFormat.getWeekSeconds(TecDateFormat.format(dateTime, 15, gnssFile.getYear().toString())), pathFileType);
        }
        return pathData;
    }

    /**
     * 读取N文件单一卫星路径数据
     * @param lines 所有记录行
     * @param index 记录行数
     * @param startIndex 卫星号
     * @return
     */
    protected double[] readSinglePath(List<String> lines, int index, int startIndex, int startLength, PathFileType pathFileType,String dateTime,String year) {
        String line = lines.get(index);
        //单一卫星轨道参数临时数组：31个参数
        double[] singlePath = new double[31];
        if (pathFileType == PathFileType.G) {
            singlePath = new double[17];
        }
        // 导航参数
        //钟偏
        singlePath[0] = Double.parseDouble(line.substring(19 + startLength, 19 * 2 + startLength).trim().replace('D', 'E'));
        //钟漂
        singlePath[1] = Double.parseDouble(line.substring(19 * 2 + startLength, 19 * 3 + startLength).trim().replace('D', 'E'));
        //钟漂率
        singlePath[2] = Double.parseDouble(line.substring(19 * 3 + startLength, 19 * 4 + startLength).trim().replace('D', 'E'));
        if (pathFileType == PathFileType.G) {
            double time = DateFormatUtils.parse(TecDateFormat.format(dateTime, 15, year),GnssFile.DATE_FORMAT).getTime();
            singlePath[15] = time;
            singlePath[16] = time;
        }
        // 单行字符串长度
        int length = 0;
        int max = 1;

        int _index = 0;
        index ++;
        //循环读参数
        for (int i = 0; i < pathFileType.getRowCount(); i++) {// 每个卫星N行记录
            line = lines.get(index ++);
            if (StringUtils.isBlank(line)) {
                continue;
            }
            length = line.length();
            if (length < 19 + startLength) {
                continue;
            }
            // 每个数据19个字符，计算每行记录个数
            max = (length - startLength) / 19;
            for (int j = 0; j < max; j++) {
                String temp = line.substring(19 * j + startLength, 19 * (j + 1) + startLength).trim();
                if (!StringUtils.isBlank(temp)) {
                    _index = i * 4 + j + startLength;
                    singlePath[_index] = Double.parseDouble(temp.replace('D', 'E'));
                }
            }
        }
        return singlePath;
    }

    /**
     * 获取数据记录第一行的行数
     *
     * @param lines
     * @return
     */
    protected int getDataIndex(List<String> lines) {
        String line = "";
        int index = 0;
        for (;index < lines.size(); index ++) {
            line = lines.get(index);
            if (line.contains("END OF HEADER")) {
                break;
            }
        }
        return index + 1;

    }

    /**
     * 验证当前卫星数据是否已存在</p>
     * 如果已存在，使用最新数据
     * @param pathData
     * @param singlePath
     * @param startNum
     */
    protected void checkSinglePath(Double[][] pathData, double[] singlePath, int startNum, int weekSeconds, PathFileType pathFileType) {
        if (singlePath == null || StringUtils.isBlank(pathData[startNum][pathFileType.getCheckIndex()]) || pathData[startNum][pathFileType.getCheckIndex()] == -99999) {
            for (int i = 0; i < singlePath.length; i ++) {
                pathData[startNum][i] = singlePath[i];
            }
            return;
        }
        // TODO 此种验证方式存疑？理论上应该可以直接根据记录的日期来判断，通过周秒计算方式判定太过复杂，效率低下
        //当pathData中已经存了某个时次的轨道参数时，需要判断该时次是不是最近时次
        double differ1 = Math.abs(pathData[startNum][pathFileType.getCheckIndex()] - weekSeconds);
        //302400 = 3.5天 = 0.5周
        // 604800 = 7天 = 1周
        if (differ1 > 302400) {
            differ1 = Math.abs(differ1 - 604800);
        }
        double differ2 = Math.abs(singlePath[pathFileType.getCheckIndex()] - weekSeconds);
        if (differ2 > 302400)
            differ2 = Math.abs(differ2 - 604800);

        if (differ2 >= differ1) {
            return;
        }
        for (int i = 0; i < singlePath.length; i ++) {
            pathData[startNum][i] = singlePath[i];
        }
    }
}
